/**
 * 此脚本文件用于删除 vue 组件中的 javascript / html / css 注释，
 * 并将删除注释后留下的空白行，如果有两行以上的空白行，则替换为一行空白行
 */

// 导入内置 path 模块
const path = require('node:path');

// 导入内置 fs 模块
const fs = require('node:fs');

// 导入去除注释的外部工具库
const strip = require('@chainsafe/strip-comments');

// 不进行注释去除的目录或文件列表：值为路径字符串，或*.扩展名，路径必须以 ./ 开头
const keepCommentsList = ['./node_modules', './.', './src', '*.json', '*.bak']; // './.' 表示根目录下隐藏的文件或目录

try {
  // 遍历目录读取文件并去除注释
  const files = fs
    .readdirSync('./test', {
      encoding: 'utf8',
      recursive: true,
      withFileTypes: true,
    })
    .filter((file) => file.isFile()); // 过滤只需要文件，不需要目录文件夹

  // 将处理后最终要进行去除注释的文件放进 fileList 数组中
  let fileList = [];

  // 循环处理递归读取到的每个文件的 dirent 对象，重组为路径文件字符串的数组进行处理
  files.forEach((file) => {
    // 是否根目录下的文件
    let isRoot = file.path === './' ? true : false;

    // 将系统对应的路径分隔符 path.sep（Windows 是 \）替换为 / 加上文件名
    let fileName =
      (isRoot ? '' : './') + file.path.split(path.sep).join('/') + (isRoot ? '' : '/') + file.name;
    // console.log('fileName:', fileName);
    if (keepCommentsList.length > 0) {
      // 文件是否是 keepCommentsList 中的文件
      let isKeep = false;
      // 匹配文件路径的正则表达式
      let regexp;

      // 将读取到的每个文件名与 keepCommentsList 中的每个 item 对比处理
      isKeep = keepCommentsList.some((item) => {
        if (typeof item === 'string') {
          // 如果不是过滤扩展名的文件
          if (!item.startsWith('*.')) {
            // 匹配文件路径的正则表达式，\b 是全字匹配（完全匹配）
            regexp = new RegExp(`^${item}\\b`, 'i');
            if (fileName.match(regexp)) {
              return true;
            }
            // console.log('item, fileName:', item, fileName);
          }
          // 如果是过滤扩展名的文件
          else {
            // 获取循环读取到的当前文件的扩展名
            let fileExtname = path.extname(fileName);
            // 获取 keepCommentsList 当前 item 的扩展名（带.号，如 .js）
            let keepItemExtname = path.extname(item);
            // console.log('fileExtname:', fileExtname);

            if (fileExtname === keepItemExtname) {
              return true;
            }
          }
        }
        return false;
      });

      // 如果文件不是 keepCommentsList 中的文件，则添加到 fileList 中
      if (!isKeep) fileList.push(fileName);
    } else {
      fileList.push(fileName);
    }
  });

  // console.log('fileList:', fileList);

  // 循环处理要去除注释的文件列表
  fileList.forEach((file) => {
    let content = fs.readFileSync(file, 'utf8');

    // 使用 strip-comments 去除 javascript / css 注释
    let newContent = strip(content, {
      line: true,
      block: true,
      keepProtected: true,
      preserveNewlines: false, // 经测试，和 true 没有什么分别，只是删除注释内容，仍留有空白行
      language: 'javascript',
    });

    // 使用 strip-comments 去除 html 注释
    newContent = strip(newContent, {
      line: true,
      block: true,
      keepProtected: true,
      preserveNewlines: false, // 经测试，和 true 没有什么分别，只是删除注释内容，仍留有空白行
      language: 'html',
    });

    // 将有两行以上空白或换行替换为两次换行（一行空白），原来是一行空白的不替换
    newContent = newContent.replace(/^(\s*\r\n(\s*)){2,}/gm, '\r\n$2');

    // 输出去除注释后的内容
    // console.log(newContent);

    // 将去除注释后的文件内容写入到原文件
    // fs.writeFileSync(`${file}_new`, newContent, { encoding: 'utf8', flush: true });
    fs.writeFileSync(file, newContent, { encoding: 'utf8', flush: true });

    // 输出已去除注释的文件列表
    console.log('File with comments removed:', file);
  });
} catch (e) {
  console.error(`Generate error: ${e}`);
}

/*
// 读取文件并去除注释
fs.readFile('./GotoTopOrBottom.vue', 'utf8', (err, data) => {
    if (err) {
        console.error(err);
        return;
    }

    // 使用 strip-comments 去除 javascript / css 注释
    let cleanedData = strip(data, {
        line: true,
        block: true,
        keepProtected: true,
        preserveNewlines: false,  // 经测试，和 true 没有什么分别，只是删除注释内容，仍留有空白行
        language: 'javascript'
    });

    // 使用 strip-comments 去除 html 注释
    cleanedData = strip(cleanedData, {
        line: true,
        block: true,
        keepProtected: true,
        preserveNewlines: false,  // 经测试，和 true 没有什么分别，只是删除注释内容，仍留有空白行
        language: 'html'
    });

    // 将有两行以上空白或换行替换为两次换行（一行空白），原来是一行空白的不替换
    cleanedData = cleanedData.replace(/^(\s*\n){2,}/gm, '\n\n');

    // 输出去除注释后的内容或将其写入新文件
    console.log(cleanedData);

    // 如果要将结果写入新文件，取消下面注释
    fs.writeFile('./GotoTopOrBottom_new.vue', cleanedData, (writeErr) => {
        if (writeErr) console.error(writeErr);
        else console.log('Comments stripped and file saved.');
    });
});
*/
